#include "ui.h"
#include <pthread.h>

/*char* changeLastChar(char* input,int len, char lastChar)
{
	input[len-1] = lastChar;
	return input;
}*/

void uiExit(){
	int i ;
	for (i = 0; i < MaxNumOfProcesses; i++){
		delProcess(i);
	}
	pthread_mutex_destroy(&filesMutex);
	stopPRM();
	printf("All processes are dead, goodbye...!\n");
}
void runUI(char* fileName)
{

	//params recieved from console , will be sent into message
	char* fileNameParam;
	pthread_mutex_init(&filesMutex,NULL);
	int exit = 0;
	char* cmd;
	char* str=malloc(sizeof(char)*500);
	while (!exit)
	{
		printf("> ");

		fgets(str,500,stdin);
		str[strlen(str)-1] = ' ';//changeLastChar(str,strlen(str),' ');

		cmd = strtok(str," ");
		if (cmd != NULL)
		{
			if (strcmp(cmd,"exit") == 0)
			{
				exit = 1; 	//sets exit flag to 1 so while loop finishes
			}
			else if (strcmp(cmd,"batchFile") == 0)
			{
				fileNameParam = strtok(NULL," ");
				FILE* f ;
				char line[50];
				f= fopen( fileNameParam , "r");
				while(fgets(line,50,f) != NULL)
				{
					if (strcmp(cmd,"exit") == 0)
					{
						exit = 1; 	//sets exit flag to 1 so while loop finishes
						break;
					}

					//printf("%s",line);
					if (line[strlen(line)-1] == '\n')
						line[strlen(line)-1] = ' ';
					else
						line[strlen(line)] = ' ';
					cmd = strtok(line," ");
					handleCommand(cmd);
				}
				fclose(f);
			}
			else
			{
				if (handleCommand(cmd) == -1)
					printf("wrong command, please try again\n");
			}
		}
	}
	FREE(str)
	uiExit();
	//TODO need to free pointers and exit the system gracefuly
}



int handleCommand(char* cmd)
{
	//params recieved from console , will be sent into message
	int pidParam;
	int byteAmmountParam;
	int vAddrParam;
	int offsetParam;
	char* fileNameParam;
	char* stringParam;
	int ans;
	if (strcmp(cmd,"createProcess") == 0)
	{
		ans = createProcess();
		if (ans == 0)
			printf("insufficient space to create new process\n");
	}
	else if (strcmp(cmd,"delProcess") == 0)
	{
		pidParam = atoi(strtok(NULL," "));
		ans = delProcess(pidParam);
		if (ans == 0)
			printf("no such process\n");
		else
			printf("%d killed Ok\n", pidParam);
	}
	else if (strcmp(cmd,"read") == 0)
	{
		vAddrParam = atoi(strtok(NULL," "));
		pidParam = atoi(strtok(NULL," "));
		byteAmmountParam = atoi(strtok(NULL," "));
		ans = read(vAddrParam, pidParam, byteAmmountParam);
		if (ans == 0)
			printf("an error has occured\n");
	}
	else if (strcmp(cmd,"loopRead") == 0)
	{
		vAddrParam = atoi(strtok(NULL," "));
		pidParam = atoi(strtok(NULL," "));
		offsetParam = atoi(strtok(NULL," "));
		byteAmmountParam = atoi(strtok(NULL," "));
		ans = loopRead(vAddrParam, pidParam, offsetParam, byteAmmountParam);
		if (ans == 0)
			printf("an error has occured\n");
	}
	else if (strcmp(cmd,"readToFile") == 0)
	{
		vAddrParam = atoi(strtok(NULL," "));
		pidParam = atoi(strtok(NULL," "));
		byteAmmountParam = atoi(strtok(NULL," "));
		fileNameParam = strtok(NULL," ");
		ans = readToFile(vAddrParam, pidParam, byteAmmountParam, fileNameParam);
		if (ans == 0)
			printf("an error has occured\n");
	}
	else if (strcmp(cmd,"loopReadToFile") == 0)
	{
		vAddrParam = atoi(strtok(NULL," "));
		pidParam = atoi(strtok(NULL," "));
		offsetParam = atoi(strtok(NULL," "));
		byteAmmountParam = atoi(strtok(NULL," "));
		char* tmp = strtok(NULL," ");
		fileNameParam = malloc(sizeof(char)* strlen(tmp));
		strcpy(fileNameParam,tmp);

		ans = loopReadToFile(vAddrParam, pidParam, offsetParam, byteAmmountParam, fileNameParam);
		if (ans == 0)
			printf("an error has occured\n");
	}
	else if (strcmp(cmd,"write") == 0)
	{
		vAddrParam = atoi(strtok(NULL," "));
		pidParam = atoi(strtok(NULL," "));
		stringParam = strtok(NULL," ");
		ans = write(vAddrParam, pidParam, stringParam);
		if (ans == 0)
			printf("an error has occured\n");
	}
	else if (strcmp(cmd,"loopWrite") == 0)
	{
		vAddrParam = atoi(strtok(NULL," "));
		pidParam = atoi(strtok(NULL," "));
		stringParam = strtok(NULL," ");
		offsetParam = atoi(strtok(NULL," "));
		byteAmmountParam = atoi(strtok(NULL," "));
		ans = loopWrite(vAddrParam, pidParam, stringParam, offsetParam, byteAmmountParam);
		if (ans == 0)
			printf("an error has occured\n");
	}
	else if (strcmp(cmd,"hitRate") == 0)
	{
		float hitRate;
		if ((hitCounter + faultCounter) == 0)
			hitRate = 0;
		else
			hitRate = (float)hitCounter / ((float)hitCounter + (float)faultCounter);
		printf("Hit rate: %f\n", hitRate);
	}
	else if (strcmp(cmd,"printMM") == 0)
	{
		printMM();
	}
	else if (strcmp(cmd,"printMMUTable") == 0)
	{
		printMMUTable();
	}
	else if (strcmp(cmd,"printRegisters") == 0)
	{
		printRegisters();
	}
	else if (strcmp(cmd,"printHat") == 0)
	{
		printHat();
	}
	else if (strcmp(cmd,"monitor") == 0)
	{
		isMonitorMode = 1;
		printf("Monitor is up\n");
	}
	else if (strcmp(cmd,"noMonitor") == 0)
	{
		isMonitorMode = 0;
		printf("Monitor is down\n");
	}
	else if (strcmp(cmd,"printDisk") == 0)
	{
		printDisk();
	}
	else
		return (int)-1;

	return ans;
}


//Create new process
int createProcess()
{
	int ans = 0;
	int i;
	for (i = 0; i < MaxNumOfProcesses; ++i )
	{
		if (processes[i].pid == -1)
		{
			//update pcb
			pcb[i].isOccupied = 1;

			//create process
			processes[i].pid = i;
			//processes[i].processPtr = malloc (sizeof(pthread_t));
			pthread_create(&processes[i].processPtr,NULL,(void*)process_exec,(void*)processes[i].pid);
			ans = 1;
			printf("Process ID: %d\n",processes[i].pid);
			break;
		}
	}
	return ans;
}

//Delete process
int delProcess(int pid)
{
	int ans = 0;
	int i;
	for (i = 0; i < MaxNumOfProcesses; ++i )
	{
		if (processes[i].pid == pid)
		{
			char* messageText = malloc(10*sizeof(char));
			strcpy(messageText,"delProcess");
			pMessage_t* message = malloc(sizeof(pMessage_t));
			createMessage(message,messageText,0,0,0,NULL,NULL);
			mbox_enqueue(pcb[i].mailbox,message);
			ans = 1;
			pthread_join(processes[i].processPtr,NULL);
			//FREE(processes[i].processPtr)
			break;
		}
	}
	return ans;
}

int read(int vAddr, int pid, int byteAmmount)
{
	int ans = 0;
	int i;
	for (i = 0; i < MaxNumOfProcesses; ++i )
	{
		if (processes[i].pid == pid)
		{
			char* messageText = malloc(4*sizeof(char));
			strcpy(messageText,"read");
			pMessage_t* message = malloc(sizeof(pMessage_t));
			createMessage(message,messageText,vAddr,0,byteAmmount,NULL,NULL);
			mbox_enqueue(pcb[i].mailbox,message);
			ans = 1;
			break;
		}
	}
	return ans;
}

int loopRead(int vAddr, int pid, int offset, int byteAmmount)
{
	int ans = 0;
	int i;
	for (i = 0; i < MaxNumOfProcesses; ++i )
	{
		if (processes[i].pid == pid)
		{
			char* messageText = malloc(8*sizeof(char));
			strcpy(messageText,"loopRead");
			pMessage_t* message = malloc(sizeof(pMessage_t));
			createMessage(message,messageText,vAddr,offset,byteAmmount,NULL,NULL);
			mbox_enqueue(pcb[i].mailbox,message);
			ans = 1;
			break;
		}
	}
	return ans;
}

int readToFile(int vAddr,int pid,int byteAmmount,char* fileName)
{

	int ans = 0;
	int i;
	for (i = 0; i < MaxNumOfProcesses; ++i )
	{
		if (processes[i].pid == pid)
		{
			char* messageText = malloc(10*sizeof(char));
			strcpy(messageText,"readToFile");
			pMessage_t* message = malloc(sizeof(pMessage_t));
			createMessage(message,messageText,vAddr,0,byteAmmount,fileName,NULL);
			mbox_enqueue(pcb[i].mailbox,message);
			ans = 1;
			break;
		}
	}

	return ans;
}

int loopReadToFile(int vAddr,int pid,int offset,int byteAmmount,char* fileName)
{
	int ans = 0;
		int i;
		for (i = 0; i < MaxNumOfProcesses; ++i )
		{
			if (processes[i].pid == pid)
			{
				char* messageText = malloc(14*sizeof(char));
				strcpy(messageText,"loopReadToFile");
				pMessage_t* message = malloc(sizeof(pMessage_t));
				createMessage(message,messageText,vAddr,offset,byteAmmount,fileName,NULL);
				mbox_enqueue(pcb[i].mailbox,message);
				ans = 1;
				break;
			}
		}
		return ans;
}

int write(int vAddr,int pid,char* stringParam)
{
	int ans = 0;
		int i;
		for (i = 0; i < MaxNumOfProcesses; ++i )
		{
			if (processes[i].pid == pid)
			{
				char* messageText = malloc(5*sizeof(char));
				strcpy(messageText,"write");
				char* stringPrm = malloc(strlen(stringParam)*sizeof(char));
				strcpy(stringPrm,stringParam);
				pMessage_t* message = malloc(sizeof(pMessage_t));
				createMessage(message,messageText,vAddr,0,strlen(stringPrm),NULL,stringPrm);
				mbox_enqueue(pcb[i].mailbox,message);
				ans = 1;
				break;
			}
		}
		return ans;
}

int loopWrite(int vAddr,int pid,char* stringParam,int offset,int byteAmmount)
{
	int ans = 0;
		int i;
		for (i = 0; i < MaxNumOfProcesses; ++i )
		{
			if (processes[i].pid == pid)
			{
				char* messageText = malloc(5*sizeof(char));
				strcpy(messageText,"loopWrite");
				char* stringPrm = malloc(strlen(stringParam)*sizeof(char));
				strcpy(stringPrm,stringParam);
				pMessage_t* message = malloc(sizeof(pMessage_t));
				createMessage(message,messageText,vAddr,offset,byteAmmount,NULL,stringPrm);
				mbox_enqueue(pcb[i].mailbox,message);
				ans = 1;
				break;
			}
		}
		return ans;
}
